package com.h3c.ptability.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.h3c.it.common.misc.lang.Assert;
import com.h3c.ptability.cache.PtEnumCache;
import com.h3c.ptability.cache.UserCache;
import com.h3c.ptability.dto.OptionsDTO;
import com.h3c.ptability.dto.PtDeptDTO;
import com.h3c.ptability.dto.PtUserDeptMonthDTO;
import com.h3c.ptability.dto.eos.EosUserClientDTO;
import com.h3c.ptability.dto.eos.UserRoleDTO;
import com.h3c.ptability.entity.PtAllWorker;
import com.h3c.ptability.entity.PtAppAdmin;
import com.h3c.ptability.entity.PtDept;
import com.h3c.ptability.entity.PtUserDeptMonth;
import com.h3c.ptability.mapper.PtAllWorkerMapper;
import com.h3c.ptability.mapper.PtAppAdminMapper;
import com.h3c.ptability.mapper.PtDeptMapper;
import com.h3c.ptability.mapper.PtUserDeptMonthMapper;
import com.h3c.ptability.service.CommService;
import com.h3c.ptability.service.EosAuthService;
import com.h3c.ptability.service.IPtDeptService;
import com.h3c.ptability.service.IPtUserDeptMonthService;
import com.h3c.ptability.support.PageQuery;
import com.h3c.ptability.utils.*;
import com.h3c.ptability.vo.PtUserDeptMonthVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * PtUserDeptMonthServiceImpl 实现类
 *
 * @author h24002
 * @date 2022-10-27
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PtUserDeptMonthServiceImpl extends ServiceImpl<PtUserDeptMonthMapper, PtUserDeptMonth> implements IPtUserDeptMonthService {

    @Resource
    private final PtUserDeptMonthMapper ptUserDeptMonthMapper;

    @Resource
    private final PtAppAdminMapper ptAppAdminMapper;

    @Resource
    private final PtDeptMapper ptDeptMapper;

    @Resource
    private IPtDeptService ptDeptService;

    @Resource
    private CommService commService;

    /**
     * 员工
     */
    @Resource
    private PtAllWorkerMapper ptAllWorkerMapper;

    /**
     * EOS相关接口
     */
    @Resource
    private EosAuthService eosAuthService;


    private Integer getCurDateMonth(Integer dateId) {
        if (Objects.isNull(dateId)) {
            Date date = new Date();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMM");
            dateId = Integer.parseInt(dateFormat.format(date));
        }
        return dateId;
    }

    /**
     * 查询应用下当前部门下的部门集合
     *
     * @param dto 应用+日期+部门
     * @return 部门列表信息，含授权主管信息
     */
    @Override
    public List<PtDeptDTO> queryChildrenDeptList(PtUserDeptMonthDTO dto) {
        //应用编码不能为空
        Assert.hasText(dto.getAppId(), CommonUtil.errorMsg("appId不能为空"));
        //初始化查询日期
        dto.setDateId(getCurDateMonth(dto.getDateId()));
        //部门列表信息
        List<PtDeptDTO> ptDeptDTOList = new ArrayList<>();

        List<PtDept> deptList = getPtDeptList();
        List<PtDept> ptDeptList = Objects.isNull(dto.getDeptId()) ? deptList : deptList.stream()
                .filter(o -> o.getParentId().equals(dto.getDeptId()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(ptDeptList)) {
            return ptDeptDTOList;
        }
        //拿到应用-日期的授权人员信息
        PtUserDeptMonthDTO userDeptMonthDTO = new PtUserDeptMonthDTO();
        userDeptMonthDTO.setAppId(dto.getAppId());
        userDeptMonthDTO.setDateId(dto.getDateId());
        List<PtUserDeptMonthVO> deptMonthList = select(userDeptMonthDTO);
        //循环部门列表，赋值  部门体系，授权用户等
        for (PtDept ptDept : ptDeptList) {
            PtDeptDTO ptDeptDTO = new PtDeptDTO();
            //模块数据复制
            BeanUtils.copyProperties(ptDept, ptDeptDTO);
            //部门体系名称抓取
            if (Objects.nonNull(ptDeptDTO.getDeptSystem())) {
                ptDeptDTO.setDeptSystemStr(PtEnumCache.getEnumDataInRedis("ptability-manage", "DEPT_SYSTEM", String.valueOf(ptDept.getDeptSystem())));
            }
            //拿到应用-日期-部门下的授权人员信息
            if (!CollectionUtils.isEmpty(deptMonthList)) {
                List<PtUserDeptMonthVO> userDeptMonthVOList = deptMonthList.stream()
                        .filter(o -> o.getDeptId().equals(ptDeptDTO.getDeptId()) && StringUtils.hasText(o.getUserName()))
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(userDeptMonthVOList)) {
                    List<String> userIds = userDeptMonthVOList.stream()
                            .map(PtUserDeptMonthVO::getUserId).distinct().collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(userIds)) {
                        ptDeptDTO.setUserIds(String.join(",", userIds));
                    }
                    List<String> userNames = userDeptMonthVOList.stream()
                            .map(PtUserDeptMonthVO::getUserName).distinct().collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(userNames)) {
                        ptDeptDTO.setUserNames(String.join(",", userNames));
                    }
                }
            }

            long selectCount = deptList.stream()
                    .filter(o -> o.getParentId().equals(ptDeptDTO.getDeptId())).count();
            ptDeptDTO.setHasChildren(selectCount > 0);
            ptDeptDTOList.add(ptDeptDTO);
        }
        return ptDeptDTOList;
    }

    /**
     * 获取有效部门架构，排除研究开发部外协
     * @return 有效部门架构
     */
    @Override
    public List<PtDept> getPtDeptList() {
        QueryWrapper<PtDept> deptQueryWrapper = new QueryWrapper<>();
        deptQueryWrapper.lambda().eq(PtDept::getDeptStatus, 1).notLike(PtDept::getDeptCodeChain, "50040000/50040426");
        return ptDeptMapper.selectList(deptQueryWrapper);
    }

    /**
     * 导入用户授权部门信息
     *
     * @param appId 应用id
     * @param file  用户授权部门信息文件
     */
    @Override
    public void importDeptUserData(String appId, MultipartFile file) {
        //解析文件内容
        String fileContent = commService.parseExcelByTemplate("PT_DEPT_IMPORT", file);
        //将文件内容转为实体对象
        List<PtDeptDTO> deptDTOList = JSONUtil.toList(JSONUtil.parseArray(fileContent), PtDeptDTO.class);
        //筛选出有授权部门且部门ID不为50040000
        List<PtDeptDTO> ptDeptDTOList = deptDTOList.stream()
                .filter(s -> StringUtils.hasText(s.getUserIds()) && s.getDeptId() != 50040000)
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ptDeptDTOList)) {
            //构建用户和授权部门对象和各类初始化数据
            HashMap<Integer, List<String>> userDeptList = new HashMap<>();
            int dateMonth = getCurDateMonth(null);
            String operatorId = UserCache.getLoginUserNameAndId();
            //需要变动的人员
            List<String> eosUserList = new ArrayList<>();
            //待删除的部门集合
            List<Integer> delDeptIdList = new ArrayList<>();
            //第1步：抓取基础部门数据
            List<PtDept> ptDeptList = getPtDeptList();
            //第2步：抓取用户列表
            QueryWrapper<PtAllWorker> allWorkerQueryWrapper = new QueryWrapper<>();
            List<PtAllWorker> allWorkerList = ptAllWorkerMapper.selectList(allWorkerQueryWrapper);
            for (PtDeptDTO deptDTO : ptDeptDTOList) {
                //无部门编码或者无授权用户就忽略
                if (Objects.isNull(deptDTO.getDeptId()) || !StringUtils.hasText(deptDTO.getUserIds())) {
                    continue;
                }
                Integer deptId = deptDTO.getDeptId();
                //授权用户为 无，表示要删除
                if ("无".equals(deptDTO.getUserIds())) {
                    delDeptIdList.add(deptId);
                }
                //补充用户-授权部门信息
                String[] userIds = deptDTO.getUserIds().split(",");
                if (userIds.length > 0) {
                    List<String> userIdList = Arrays.stream(userIds).distinct().collect(Collectors.toList());
                    //找出员工授权的部门列表
                    List<String> addUserIdList = allWorkerList.stream()
                            .map(PtAllWorker::getWorkerId)
                            .filter(userIdList::contains).distinct().collect(Collectors.toList());
                    //如果存在新增部门，则构成插入对象
                    if (!CollectionUtils.isEmpty(addUserIdList)) {
                        delDeptIdList.add(deptId);
                        if (userDeptList.containsKey(deptId)) {
                            userDeptList.get(deptId).addAll(addUserIdList);
                        } else {
                            userDeptList.put(deptId, addUserIdList);
                        }
                    }
                }
            }

            //待新增的用户授权部门数据
            List<PtUserDeptMonth> addUserDeptMonthList = new ArrayList<>();
            if (userDeptList.size() > 0) {
                userDeptList.forEach((deptId, userIdList) -> {
                    userIdList = userIdList.stream().distinct().collect(Collectors.toList());
                    eosUserList.addAll(userIdList);
                    for (String addUserId : userIdList) {
                        PtUserDeptMonth addUserDeptMonthModel = new PtUserDeptMonth();
                        addUserDeptMonthModel.setAppId(appId);
                        addUserDeptMonthModel.setDateId(dateMonth);
                        addUserDeptMonthModel.setUserId(addUserId);
                        addUserDeptMonthModel.setDeptId(deptId);
                        addUserDeptMonthModel.setOperatorId(operatorId);
                        addUserDeptMonthModel.setOperateTime(new Date());
                        addUserDeptMonthList.add(addUserDeptMonthModel);
                    }

                });
            }
            //去除 要删除权限和更新权限的人员部门信息
            if (delDeptIdList.size() > 0) {
                delDeptIdList = delDeptIdList.stream().distinct().collect(Collectors.toList());
                QueryWrapper<PtUserDeptMonth> delQueryWrapper = new QueryWrapper<>();
                delQueryWrapper.lambda().eq(PtUserDeptMonth::getAppId, appId)
                        .eq(PtUserDeptMonth::getDateId, dateMonth)
                        .in(PtUserDeptMonth::getDeptId, delDeptIdList);
                ptUserDeptMonthMapper.delete(delQueryWrapper);
            }
            //更新权限的人员部门信息
            if (!CollectionUtils.isEmpty(addUserDeptMonthList)) {
                insertList(addUserDeptMonthList);
            }
            //补充部门数据
            modifyUserDeptMonth(dateMonth, appId, ptDeptList, eosUserList);
        }
    }


    /**
     * 补充或修复员工的授权部门信息
     *
     * @param dateMonth   日期
     * @param appId       应用编码
     * @param ptDeptList  部门列表
     * @param eosUserList 需要修改的已授权部门 的用户列表信息
     */
    @Override
    public void modifyUserDeptMonth(int dateMonth, String appId, List<PtDept> ptDeptList, List<String> eosUserList) {
        if (!CollectionUtils.isEmpty(eosUserList)) {
            //抓取用户授权部门列表信息
            QueryWrapper<PtUserDeptMonth> userDeptMonthQueryWrapper = new QueryWrapper<>();
            userDeptMonthQueryWrapper.lambda()
                    .eq(PtUserDeptMonth::getAppId, appId)
                    .eq(PtUserDeptMonth::getDateId, dateMonth);
            List<PtUserDeptMonth> userDeptMonthList = ptUserDeptMonthMapper.selectList(userDeptMonthQueryWrapper);
            //用户和授权部门集合
            Map<String, List<Integer>> userDeptList = new HashMap<>();
            eosUserList = eosUserList.stream().distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(userDeptMonthList)) {
                //循环查询用户授权部门信息
                for (String eosUserId : eosUserList) {
                    //无工号人员不予补充
                    if (!StringUtils.hasText(eosUserId)) {
                        continue;
                    }
                    //找出员工授权的部门列表
                    List<Integer> deptList = userDeptMonthList.stream()
                            .filter(o -> o.getUserId().equals(eosUserId))
                            .map(PtUserDeptMonth::getDeptId).distinct()
                            .collect(Collectors.toList());
                    //找出员工授权部门下的所有下级部门，不存在则补充
                    List<Integer> addDeptList = new ArrayList<>();
                    expandDept(ptDeptList, deptList, addDeptList);
                    if (!CollectionUtils.isEmpty(addDeptList)) {
                        if (userDeptList.containsKey(eosUserId)) {
                            userDeptList.get(eosUserId).addAll(addDeptList);
                        } else {
                            userDeptList.put(eosUserId, addDeptList);
                        }
                    }
                }
            }
            if (userDeptList.size() > 0) {
                //待新增的用户授权部门数据
                List<PtUserDeptMonth> addUserDeptMonthList = new ArrayList<>();
                userDeptList.forEach((eosUserId, addDeptIdList) -> {
                    //找出员工授权的部门列表
                    List<Integer> deptList = userDeptMonthList.stream()
                            .filter(o -> o.getUserId().equals(eosUserId))
                            .map(PtUserDeptMonth::getDeptId).distinct()
                            .collect(Collectors.toList());
                    //如果存在新增部门，则构成插入对象
                    if (!CollectionUtils.isEmpty(addDeptIdList)) {
                        if (!CollectionUtils.isEmpty(deptList)) {
                            addDeptIdList = addDeptIdList.stream().filter(o -> !deptList.contains(o)).distinct().collect(Collectors.toList());
                        } else {
                            addDeptIdList = addDeptIdList.stream().distinct().collect(Collectors.toList());
                        }
                        addUserDeptMonthList.addAll(makePtUserDeptMonthList(dateMonth, appId, eosUserId, addDeptIdList));
                    }
                });
                if (!CollectionUtils.isEmpty(addUserDeptMonthList)) {
                    insertList(addUserDeptMonthList);
                }
            }
        }
    }


    /**
     * 拓展部门集合，加载下级部门列表
     *
     * @param ptDeptList  部门集合
     * @param deptList    当前部门列表
     * @param addDeptList 待补充的部门列表
     */
    @Override
    public void expandDept(List<PtDept> ptDeptList, List<Integer> deptList, List<Integer> addDeptList) {
        if (!CollectionUtils.isEmpty(deptList)) {
            for (Integer deptId : deptList) {
                //找出下级部门数据:第一次寻找
                List<Integer> firstDeptList = ptDeptList.stream()
                        .filter(o -> o.getParentId().equals(deptId) && o.getDeptLevel() <= 4)
                        .map(PtDept::getDeptId).distinct()
                        .collect(Collectors.toList());
                //假如说添加一级下的二级部门集合
                if (!CollectionUtils.isEmpty(firstDeptList)) {
                    for (Integer firstDeptId : firstDeptList) {
                        //找出下级部门数据:第一次寻找
                        List<Integer> sedDeptList = ptDeptList.stream()
                                .filter(o -> o.getParentId().equals(firstDeptId) && o.getDeptLevel() <= 4)
                                .map(PtDept::getDeptId).distinct()
                                .collect(Collectors.toList());
                        //假如说添加二级下的三级部门集合
                        if (!CollectionUtils.isEmpty(sedDeptList)) {
                            for (Integer sedDeptId : sedDeptList) {
                                //找出下级部门数据:第一次寻找
                                List<Integer> trdDeptList = ptDeptList.stream()
                                        .filter(o -> o.getParentId().equals(sedDeptId) && o.getDeptLevel() <= 4)
                                        .map(PtDept::getDeptId).distinct()
                                        .collect(Collectors.toList());
                                //假如说添加三级下的四级部门集合
                                if (!CollectionUtils.isEmpty(trdDeptList)) {
                                    addDeptList.addAll(trdDeptList);
                                }
                            }
                            addDeptList.addAll(sedDeptList);
                        }
                    }
                    addDeptList.addAll(firstDeptList);
                }
            }
        }
    }

    /**
     * 查询用户授权的部门树(一二三级部门)
     *
     * @param dto 查询条件
     * @return 部门树结构
     */
    @Override
    public List<OptionsDTO> queryUserDeptMonthTree(PtUserDeptMonthDTO dto) {
        //初始化查询日期
        dto.setDateId(getCurDateMonth(dto.getDateId()));
        //初始化查询部门级别
        if (Objects.isNull(dto.getDeptLevel())) {
            dto.setDeptLevel(3);
        }
        //初始化查询基部门
        if (Objects.isNull(dto.getDeptId())) {
            dto.setDeptId(50040000);
        }
        //最小部门层级
        Integer deptLevel = dto.getDeptLevel();
        //初始化部门
        List<PtDept> ptDeptList = getPtDeptList();
        ptDeptList = ptDeptList.stream()
                .filter(o -> o.getDeptLevel() > 0 && o.getDeptLevel() <= deptLevel)
                .collect(Collectors.toList());
        List<Integer> allDeptIdList = ptDeptList.stream().map(PtDept::getDeptId).distinct().collect(Collectors.toList());
        //有部门结构
        if (!CollectionUtils.isEmpty(ptDeptList)) {
            if (Objects.nonNull(dto.getIsBigRole()) && dto.getIsBigRole()) {
                return doUserDeptMonthChild(1, deptLevel, dto.getDeptId(), ptDeptList, allDeptIdList, allDeptIdList);
            }
            QueryWrapper<PtUserDeptMonth> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(PtUserDeptMonth::getAppId, dto.getAppId())
                    .eq(PtUserDeptMonth::getDateId, dto.getDateId())
                    .eq(PtUserDeptMonth::getUserId, dto.getUserId());
            List<PtUserDeptMonth> deptMonthList = ptUserDeptMonthMapper.selectList(queryWrapper);
            if (!CollectionUtils.isEmpty(deptMonthList)) {
                List<Integer> userDeptIdList = deptMonthList.stream().map(PtUserDeptMonth::getDeptId).distinct().collect(Collectors.toList());
                List<Integer> authorizedDeptIdList = new ArrayList<>();
                authorizedDeptIdList.addAll(userDeptIdList);
                extendDeptParentId(deptLevel, ptDeptList, userDeptIdList);
                return doUserDeptMonthChild(1, deptLevel, dto.getDeptId(), ptDeptList, userDeptIdList, authorizedDeptIdList);
            }
        }
        return null;
    }

    /**
     * 补充上级部门
     *
     * @param curDeptLevel   查询的部门层级
     * @param ptDeptList     部门信息
     * @param userDeptIdList 用户授权部门
     */
    private void extendDeptParentId(Integer curDeptLevel, List<PtDept> ptDeptList, List<Integer> userDeptIdList) {
        //判断上层部门是否在授权列表中，若不在，则构造上级部门编码
        if (curDeptLevel != 1) {
            List<Integer> dept1Codes = ptDeptList.stream()
                    .filter(o -> o.getDeptLevel().equals(curDeptLevel) && userDeptIdList.contains(o.getDeptId()) && !userDeptIdList.contains(o.getParentId()))
                    .map(PtDept::getParentId).distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(dept1Codes)) {
                userDeptIdList.addAll(dept1Codes);
            }
            extendDeptParentId(curDeptLevel - 1, ptDeptList, userDeptIdList);
        }
    }

    /**
     * 构建部门树
     *
     * @param curDeptLevel         当前部门层级
     * @param limitDeptLevel       最小部门层级
     * @param parentDeptId         上级部门编码
     * @param ptDeptList           部门信息
     * @param userDeptIdList       授权部门信息
     * @param authorizedDeptIdList 特殊权限部门id
     * @return 授权部门树
     */
    private List<OptionsDTO> doUserDeptMonthChild(Integer curDeptLevel, Integer limitDeptLevel, Integer parentDeptId, List<PtDept> ptDeptList, List<Integer> userDeptIdList, List<Integer> authorizedDeptIdList) {
        //初始化一级部门层级
        List<OptionsDTO> list = new ArrayList<>();
        //一级部门层级
        if (curDeptLevel <= limitDeptLevel) {
            List<PtDept> deptList = ptDeptList.stream()
                    .filter(o -> o.getParentId().equals(parentDeptId) && o.getDeptLevel().equals(curDeptLevel) && userDeptIdList.contains(o.getDeptId()))
                    .distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(deptList)) {
                for (PtDept ptDept : deptList) {
                    OptionsDTO opt = new OptionsDTO(String.valueOf(ptDept.getDeptId()), ptDept.getDeptName());
                    opt.setDisabled(!authorizedDeptIdList.contains(ptDept.getDeptId()));
                    opt.setDeptLevel(ptDept.getDeptLevel());
                    opt.setParentId(ptDept.getParentId());
                    opt.setDept1Code(StrUtil.splitTrim(ptDept.getDeptCodeChain(), "/").get(1));
                    List<OptionsDTO> child = doUserDeptMonthChild(curDeptLevel + 1, limitDeptLevel, ptDept.getDeptId(), ptDeptList, userDeptIdList, authorizedDeptIdList);
                    if (!CollectionUtils.isEmpty(child) && child.size() > 0) {
                        opt.setChildren(child);
                    }
                    list.add(opt);
                }
            }
        }


        return list;
    }

    /**
     * 查询部门树(一二三级部门)
     *
     * @param dto 查询条件
     * @return 部门树结构
     */
    @Override
    public List<OptionsDTO> queryDeptTreeSelection(PtUserDeptMonthDTO dto) {
        //初始化查询日期
        dto.setDateId(getCurDateMonth(dto.getDateId()));
        //初始化查询基部门
        if (Objects.isNull(dto.getDeptId())) {
            dto.setDeptId(50040000);
        }
        //初始化查询部门级别
        if (Objects.isNull(dto.getDeptLevel())) {
            dto.setDeptLevel(3);
        }
        //初始化部门
        List<PtDept> ptDeptList = getPtDeptList();
        return doChildDept(dto.getDeptLevel(), dto.getDeptId(), ptDeptList);
    }

    /**
     * 加载下级部门
     *
     * @param deptLevel    最小部门级别
     * @param parentDeptId 父级部门编码
     * @param ptDeptList   部门集合
     * @return 下级部门集合
     */
    private List<OptionsDTO> doChildDept(Integer deptLevel, Integer parentDeptId, List<PtDept> ptDeptList) {
        //一级、二级、三级部门集合
        List<OptionsDTO> optionList = new ArrayList<>();
        //查找下级部门集合
        List<PtDept> childDeptList = ptDeptList.stream()
                .filter(s -> s.getParentId().equals(parentDeptId) && s.getDeptLevel() <= deptLevel)
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(childDeptList)) {
            for (PtDept childDept : childDeptList) {
                OptionsDTO childDto = new OptionsDTO(String.valueOf(childDept.getDeptId()), childDept.getDeptName());
                childDto.setChildren(doChildDept(deptLevel, childDept.getDeptId(), ptDeptList));
                optionList.add(childDto);
            }
        }
        return optionList;
    }

    /**
     * 检查操作权限
     *
     * @param appId 应用编码
     */
    @Override
    public void checkOperationValid(String appId) {
        //查询参数判断
        Assert.hasText(appId, CommonUtil.errorMsg("应用编码不可为空"));
        //当前登录用户
        String userId = UserCache.getLoginUserId();
        //应用管理员才有权限查询和操作
        LambdaQueryWrapper<PtAppAdmin> appAdminQueryWrapper = new LambdaQueryWrapper<>();
        appAdminQueryWrapper.eq(PtAppAdmin::getUserId, userId);
        List<PtAppAdmin> ptAppAdmins = ptAppAdminMapper.selectList(appAdminQueryWrapper);
        Assert.notEmpty(ptAppAdmins, CommonUtil.errorMsg("无权操作"));
        List<String> appList = ptAppAdmins.stream().map(PtAppAdmin::getAppId).distinct().collect(Collectors.toList());
        Assert.isTrue(appList.contains(BusiEnumDefine.PT_LOG_APP_NAME) || appList.contains(appId), CommonUtil.errorMsg("无权操作"));
    }

    /**
     * 查询授权的部门数据
     *
     * @param pageQuery 查询条件
     * @return 基础信息（应用-部门-用户）
     */
    @Override
    public IPage<PtUserDeptMonthVO> selectPage(PageQuery<PtUserDeptMonthDTO> pageQuery) {
        PtUserDeptMonthDTO condition = pageQuery.getCondition();
        condition.setDateId(getCurDateMonth(condition.getDateId()));
        // 设置分页
        Page<PtUserDeptMonth> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        // 添加搜索条件
        QueryWrapper<PtUserDeptMonth> userDeptMonthQueryWrapper = new QueryWrapper<>();
        userDeptMonthQueryWrapper.eq("pudm.app_id", condition.getAppId()).eq("pudm.date_id", condition.getDateId())
                .eq(Objects.nonNull(condition.getDeptId()), "pudm.dept_id", condition.getDeptId())
                .eq(StringUtils.hasText(condition.getUserId()), "pudm.user_id", condition.getUserId());
        // 添加排序
        MybatisUtils.setOrderBy(page, pageQuery.getSortList());
        IPage<PtUserDeptMonthVO> mapPage = ptUserDeptMonthMapper.selectPtUserDeptMonthInPage(userDeptMonthQueryWrapper, page);
        return mapPage;
    }


    /**
     * 插入授权的部门数据
     *
     * @param info 实体
     */
    @Override
    public void insert(PtUserDeptMonth info) {
        info.setDateId(getCurDateMonth(info.getDateId()));
        // 检查字段
        FieldUtils.checkFieldsExclude(info, "id");
        // 添加
        this.save(info);
    }

    /**
     * 插入授权的部门数据
     *
     * @param dto 实体
     */
    @Override
    public void insertDto(PtUserDeptMonthDTO dto) {
        dto.setDateId(getCurDateMonth(dto.getDateId()));
        // 转化类型
        PtUserDeptMonth ptUserDeptMonth = BeanUtil.copyProperties(dto, PtUserDeptMonth.class);
        // 检查字段
        FieldUtils.checkFieldsExclude(ptUserDeptMonth, "id");
        //补充操作人和操作日期
        ptUserDeptMonth.setOperateTime(new Date());
        ptUserDeptMonth.setOperatorId(UserCache.getLoginUserNameAndId());
        // 添加
        this.save(ptUserDeptMonth);
    }

    /**
     * 重置用户授权的部门数据
     *
     * @param dto 实体
     */
    @Override
    public void update(PtUserDeptMonthDTO dto) {
        dto.setDateId(getCurDateMonth(dto.getDateId()));
        List<PtUserDeptMonth> list = new ArrayList<>();
        String loginUserNameAndId = UserCache.getLoginUserNameAndId();
        //再新增用户授权的部门数据
        for (Integer deptId : dto.getDeptIdList()) {
            PtUserDeptMonth deptMonth = new PtUserDeptMonth();
            deptMonth.setDeptId(deptId);
            deptMonth.setAppId(dto.getAppId());
            deptMonth.setUserId(dto.getUserId());
            deptMonth.setDateId(dto.getDateId());
            deptMonth.setOperatorId(loginUserNameAndId);
            deptMonth.setOperateTime(new Date());
            list.add(deptMonth);
        }
        //先删除用户授权的部门数据
        delete(dto);
        // 添加
        this.saveBatch(list);
    }

    /**
     * 批量插入授权的部门数据
     *
     * @param dtoList 授权的部门数据
     */
    @Override
    public void insertDtoList(List<PtUserDeptMonthDTO> dtoList) {
        Assert.notEmpty(dtoList, CommonUtil.errorMsg("插入数据不可为空"));
        // 转化类型
        Date date = new Date();
        String loginUserNameAndId = UserCache.getLoginUserNameAndId();
        List<PtUserDeptMonth> list = BeanUtil.copyToList(dtoList, PtUserDeptMonth.class);
        for (PtUserDeptMonth userDeptMonth : list) {
            // 检查字段
            FieldUtils.checkFieldsExclude(userDeptMonth, "id");
            userDeptMonth.setDateId(getCurDateMonth(userDeptMonth.getDateId()));
            //补充操作人和操作日期
            userDeptMonth.setOperateTime(date);
            userDeptMonth.setOperatorId(loginUserNameAndId);
        }
        // 批量添加
        this.saveBatch(list);
    }

    /**
     * 批量插入授权的部门数据
     *
     * @param list 授权的部门数据
     */
    @Override
    public void insertList(List<PtUserDeptMonth> list) {
        Assert.notEmpty(list, CommonUtil.errorMsg("插入数据不可为空"));
        for (PtUserDeptMonth userDeptMonth : list) {
            // 检查字段
            FieldUtils.checkFieldsExclude(userDeptMonth, "id");
        }
        // 批量添加
        this.saveBatch(list);
    }

    /**
     * 删除授权人员部门数据
     *
     * @param condition 查询条件
     */
    @Override
    public void delete(PtUserDeptMonthDTO condition) {
        condition.setDateId(getCurDateMonth(condition.getDateId()));
        QueryWrapper<PtUserDeptMonth> userDeptMonthQueryWrapper = new QueryWrapper<>();
        userDeptMonthQueryWrapper.lambda().eq(PtUserDeptMonth::getAppId, condition.getAppId())
                .eq(PtUserDeptMonth::getDateId, condition.getDateId())
                .eq(Objects.nonNull(condition.getDeptId()), PtUserDeptMonth::getDeptId, condition.getDeptId())
                .eq(StringUtils.hasText(condition.getUserId()), PtUserDeptMonth::getUserId, condition.getUserId());
        ptUserDeptMonthMapper.delete(userDeptMonthQueryWrapper);
    }

    /**
     * 查询授权人员部门数据
     *
     * @param condition 查询条件
     * @return 基础信息（应用-部门-用户）
     */
    @Override
    public List<PtUserDeptMonthVO> select(PtUserDeptMonthDTO condition) {
        condition.setDateId(getCurDateMonth(condition.getDateId()));
        QueryWrapper<PtUserDeptMonth> userDeptMonthQueryWrapper = new QueryWrapper<>();
        userDeptMonthQueryWrapper.eq("pudm.app_id", condition.getAppId()).eq("pudm.date_id", condition.getDateId())
                .eq(Objects.nonNull(condition.getDeptId()), "pudm.dept_id", condition.getDeptId())
                .eq(StringUtils.hasText(condition.getUserId()), "pudm.user_id", condition.getUserId())
                .le(Objects.nonNull(condition.getDeptLevel()), "pd.dept_level", condition.getDeptLevel());
        return ptUserDeptMonthMapper.selectPtUserDeptMonth(userDeptMonthQueryWrapper);
    }

    @Override
    public List<String> userIdOfDeptRole(PtUserDeptMonthDTO condition) {

        List<String> allAuthorityUserIds =  list(new QueryWrapper<PtUserDeptMonth>().lambda()
                .eq(PtUserDeptMonth::getDeptId, condition.getDeptId())
                .eq(PtUserDeptMonth::getDateId, condition.getDateId())
                .eq(PtUserDeptMonth::getAppId, condition.getAppId()))
                .stream().map(PtUserDeptMonth::getUserId).collect(Collectors.toList());

        Set<String> roleUserIds = new HashSet<>();
        for (String role : condition.getRoles()) {
            List<String> temp = eosAuthService.getUserListByRoleCode(role, condition.getAppId(), 1, 999).stream().map(EosUserClientDTO::getEmpCode).collect(Collectors.toList());
            roleUserIds.addAll(temp);
        }

        return  allAuthorityUserIds.stream().filter(o -> roleUserIds.contains(o)).collect(Collectors.toList());
    }

    /**
     * 月度授权部门数据初始化
     *
     * @param dateMonth 可查询年月
     * @param appId     授权应用
     * @return 初始化结果信息
     */
    @Override
    public String initPtUserDeptMonth(int dateMonth, String appId) {
        QueryWrapper<PtUserDeptMonth> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(PtUserDeptMonth::getAppId, appId).eq(PtUserDeptMonth::getDateId, dateMonth);
        Integer selectCount = ptUserDeptMonthMapper.selectCount(wrapper);
        if (selectCount == 0) {
            DateTime dateTime = DateUtil.parse(dateMonth + "", "yyyyMM");
            dateTime = DateUtil.offsetMonth(dateTime, -1);
            int preDateMonth = Integer.parseInt(dateTime.toString("yyyyMM"));
            Integer addCount = ptUserDeptMonthMapper.InitPtUserDeptMonth(appId, dateMonth, "system", preDateMonth);
            return "复制" + preDateMonth + "授权部门数据：" + addCount;
        } else {
            return "无需复制授权部门数据";
        }
    }

    /**
     * 重置人力看板 部门主管角色 用户列表
     *
     * @param deptManageRole 部门主管角色
     * @param appId          人力看板
     * @param deptManagerIds 部门主管信息
     * @return 重置人力看板 部门主管角色用户结果
     */
    @Override
    public String resetDeptManage(String deptManageRole, String appId, List<String> deptManagerIds) {
        String opDesc = "重置角色用户" + deptManageRole;
        try {
            if (!CollectionUtils.isEmpty(deptManagerIds)) {
                //更新部门授权用户列表
                LambdaQueryWrapper<PtAllWorker> allWorkerQueryWrapper = new QueryWrapper<PtAllWorker>().lambda()
                        .in(PtAllWorker::getWorkerId, deptManagerIds);
                List<PtAllWorker> allWorkerList = ptAllWorkerMapper.selectList(allWorkerQueryWrapper);
                if (!CollectionUtils.isEmpty(allWorkerList)) {
                    List<String> deptManagers = allWorkerList.stream()
                            .map(PtAllWorker::getDomainAccount)
                            .filter(StringUtils::hasText)
                            .distinct().collect(Collectors.toList());
                    UserRoleDTO mdyUserRole = new UserRoleDTO();
                    mdyUserRole.setAppId(appId);
                    mdyUserRole.setRoleCode(deptManageRole);
                    mdyUserRole.setAccountList(deptManagers);
                    mdyUserRole.setRebindUserRole(true);
                    String mdyResult = eosAuthService.resetUserRole(mdyUserRole);
                    return opDesc + " 更新用户" + deptManagers.size() + ",参数:" + JSONUtil.toJsonStr(mdyUserRole) + ",返回:" + mdyResult;
                } else {
                    throw new AppBusinessException(opDesc + "结果：没抓取到部门主管的人员信息");
                }
            } else {
                throw new AppBusinessException(opDesc + "结果：没抓取到部门主管数据");
            }
        } catch (Exception ex) {
            throw new AppBusinessException(opDesc + "异常：" + JSONUtil.toJsonStr(ex));
        }
    }

    /**
     * 补充 大角色人员 一级授权部门信息
     *
     * @param dateMonth 日期
     * @param appId     人力看板
     * @param deptList  部门列表
     * @param userList  需要修改的已授权部门 的用户列表信息
     * @return 补充大角色人员的一级授权部门信息结果
     */
    @Override
    public String replenishTopUserDeptMonth(int dateMonth, String appId, List<PtDept> deptList, List<String> userList) {
        String opDesc = "补充大角色人员的一级授权部门信息";
        try {
            if (!CollectionUtils.isEmpty(userList) && !CollectionUtils.isEmpty(deptList)) {
                //待新增的用户授权部门数据
                List<PtUserDeptMonth> addUserDeptMonthList = new ArrayList<>();
                //找到这些人的授权一级部门情况
                List<Integer> firstDeptIdList = deptList.stream().filter(o -> o.getDeptLevel().equals(1))
                        .map(PtDept::getDeptId).distinct().collect(Collectors.toList());
                //找到租户下的月度授权列表
                QueryWrapper<PtUserDeptMonth> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(PtUserDeptMonth::getAppId, appId)
                        .eq(PtUserDeptMonth::getDateId, dateMonth)
                        .in(PtUserDeptMonth::getUserId, userList);
                List<PtUserDeptMonth> deptMonthList = ptUserDeptMonthMapper.selectList(queryWrapper);
                //循环遍历人员，补充一级部门授权
                for (String userId : userList) {
                    //找到主管的月度授权数据
                    List<Integer> userDeptIdList = deptMonthList.stream().filter(o -> o.getUserId().equals(userId))
                            .map(PtUserDeptMonth::getDeptId).distinct().collect(Collectors.toList());
                    //已存在已授权的一级部门数据，则补充还未授权的。否则补充全部一级部门授权数据
                    if (!CollectionUtils.isEmpty(userDeptIdList)) {
                        //将没添加的一级部门添加进去
                        List<Integer> unAddDeptIdList = firstDeptIdList.stream().filter(o -> !userDeptIdList.contains(o)).collect(Collectors.toList());
                        if (!CollectionUtils.isEmpty(unAddDeptIdList)) {
                            addUserDeptMonthList.addAll(makePtUserDeptMonthList(dateMonth, appId, userId, unAddDeptIdList));
                        }
                    } else {
                        addUserDeptMonthList.addAll(makePtUserDeptMonthList(dateMonth, appId, userId, firstDeptIdList));
                    }
                }
                if (!CollectionUtils.isEmpty(addUserDeptMonthList)) {
                    insertList(addUserDeptMonthList);
                    return opDesc + "成功，补充数据量：" + addUserDeptMonthList.size();
                } else {
                    return opDesc + "失败：未找到待补充的一级部门数据";
                }
            } else {
                return opDesc + "失败：大角色用户或部门组织数据缺失";
            }
        } catch (Exception ex) {
            throw new AppBusinessException(opDesc + "异常：" + JSONUtil.toJsonStr(ex));
        }
    }

    /**
     * 组装月度部门授权数据
     *
     * @param dateMonth       年月度
     * @param appId           应用编号
     * @param userId          用户
     * @param unAddDeptIdList 待新增的部门集合
     * @return 月度部门授权数据
     */
    private List<PtUserDeptMonth> makePtUserDeptMonthList(int dateMonth, String appId, String userId, List<Integer> unAddDeptIdList) {
        //待新增的用户授权部门数据
        List<PtUserDeptMonth> addUserDeptMonthList = new ArrayList<>();
        for (Integer unAddDeptId : unAddDeptIdList) {
            PtUserDeptMonth addUserDeptMonthModel = new PtUserDeptMonth();
            addUserDeptMonthModel.setAppId(appId);
            addUserDeptMonthModel.setDateId(dateMonth);
            addUserDeptMonthModel.setUserId(userId);
            addUserDeptMonthModel.setDeptId(unAddDeptId);
            addUserDeptMonthModel.setOperatorId("system");
            addUserDeptMonthModel.setOperateTime(new Date());
            addUserDeptMonthList.add(addUserDeptMonthModel);
        }
        return addUserDeptMonthList;
    }

    /**
     * 补充 自动主管角色 的授权部门数据
     *
     * @param dateMonth       日期
     * @param appId           人力看板
     * @param eosUserList     手工授权部门的角色人员列表
     * @param deptManagerList 一二级部门主管信息
     * @return 补充自动主管角色的授权部门数据结果
     */
    @Override
    public String replenishManageDeptManageMonth(int dateMonth, String appId, List<String> eosUserList, List<PtDept> deptManagerList) {
        String opDesc = "补充自动主管角色人员的各级授权部门信息";
        try {
            //待新增的用户授权部门数据
            List<PtUserDeptMonth> addUserDeptMonthList = new ArrayList<>();
            //第1步：去除非手工增添人员的用户授权部门数据
            if (!CollectionUtils.isEmpty(eosUserList)) {
                eosUserList = eosUserList.stream().distinct().collect(Collectors.toList());
                QueryWrapper<PtUserDeptMonth> userDeptMonthQueryWrapper = new QueryWrapper<>();
                userDeptMonthQueryWrapper.lambda().eq(PtUserDeptMonth::getAppId, appId)
                        .eq(PtUserDeptMonth::getDateId, dateMonth)
                        .notIn(PtUserDeptMonth::getUserId, eosUserList);
                ptUserDeptMonthMapper.delete(userDeptMonthQueryWrapper);
                opDesc = opDesc + "[要删除全部月度数据：" + appId + "," + dateMonth + "],保留人群[" + String.join(",", eosUserList) + "]";
            } else {
                opDesc = opDesc + "[要删除全部月度数据：" + appId + "," + dateMonth + "]";
                QueryWrapper<PtUserDeptMonth> userDeptMonthQueryWrapper = new QueryWrapper<>();
                userDeptMonthQueryWrapper.lambda().eq(PtUserDeptMonth::getAppId, appId)
                        .eq(PtUserDeptMonth::getDateId, dateMonth);
                ptUserDeptMonthMapper.delete(userDeptMonthQueryWrapper);
            }
            //第2步：补充自动授权角色人员的授权部门数据
            for (PtDept ptDept : deptManagerList) {
                //找到部门上的主管
                String userId = ptDept.getDeptManagerId();
                if (StringUtils.hasText(userId)) {
                    //解析主管数据并遍历
                    List<String> managerIds = CommonUtil.getDeptManagerSplitId(userId);
                    for (String managerId : managerIds) {
                        //用户已存在非手工角色中则过滤，否则添加对应的人员-部门数据
                        if (!eosUserList.contains(managerId)) {
                            PtUserDeptMonth addUserDeptMonthModel = new PtUserDeptMonth();
                            addUserDeptMonthModel.setAppId(appId);
                            addUserDeptMonthModel.setDateId(dateMonth);
                            addUserDeptMonthModel.setUserId(managerId);
                            addUserDeptMonthModel.setDeptId(ptDept.getDeptId());
                            addUserDeptMonthModel.setOperatorId("system");
                            addUserDeptMonthModel.setOperateTime(new Date());
                            addUserDeptMonthList.add(addUserDeptMonthModel);
                        }
                    }
                }
            }
            if (!CollectionUtils.isEmpty(addUserDeptMonthList)) {
                insertList(addUserDeptMonthList);
                return opDesc + "成功，补充数据量：" + addUserDeptMonthList.size();
            } else {
                return opDesc + "失败：未找到待补充的自动主管的部门数据";
            }
        } catch (Exception ex) {
            throw new AppBusinessException(opDesc + "异常：" + JSONUtil.toJsonStr(ex));
        }
    }


}
